home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Practical Algorithms for Image Analysis
/
Practical Algorithms for Image Analysis.iso
/
TARFILE.GZ
/
tarfile
/
ch_5.3
/
fitpolyg
/
fitpolyg.c
< prev
next >
Wrap
C/C++ Source or Header
|
1999-09-11
|
9KB
|
289 lines
/*
* fitpolyg.c
*
* Practical Algorithms for Image Analysis
*
* Copyright (c) 1997, 1998, 1999 MLMSoftwareGroup, LLC
*/
/* FITPOLYG: program performs polygonal fit upon image lines, where
* input is in PCC code
* usage: fitpolyg infile outimg [-t THRESHOLD] [-c] [-w file] [-L]
*/
#define THRESH_DFLT 5
#include <stdio.h>
#include <stdlib.h>
#include <images.h>
#include <string.h>
#include "tiffimage.h"
#include "pcc2.h" /* for PCC programs */
extern void print_sos_lic ();
unsigned char *fcCode; /* code storage */
long nByteCode; /* no. bytes in code storage */
long xytoline (struct point *, long *, long *, long *);
long usage (short);
long input (int, char **, long *, short *, char *);
float slope (int x1, int y1, int x2, int y2);
main (argc, argv)
int argc;
char *argv[];
{
Image *imgO; /* pointer to output image structure */
unsigned char **image; /* output image array */
long width, height; /* image size */
struct point imgSize; /* image size */
long thresh; /* threshold for fit */
short coordFlag; /* flag = 1, print fit coord.s; or 0 */
struct point *data; /* data curve */
long nData; /* no. coords in data curve */
long nSegments; /* number of segments found */
long nStructs; /* number of line structures found */
long kLine; /* line number */
long lengthSqr, area; /* length sqr.ed and area of line fits */
long deltaX, deltaY; /* x and y increments for line fits */
long drawline8 (); /* joins points in 8-connected lines */
long nFits; /* number of polygonal fits */
struct point pt0, pt1; /* points to connect fits between */
long x, y;
long i;
char segfile[256];
int segfileFlag = 0;
FILE *segstream;
segfile[0] = '\0';
/* user input */
if (input (argc, argv, &thresh, &coordFlag, segfile) < 0)
return (-1);
if (strlen (segfile)) {
segfileFlag = 1;
segstream = fopen (segfile, "w+");
fprintf (segstream, " \n"); /* write blanks for later fseek */
}
/* open input PCC file */
if (pccread (argv[1], &fcCode, &nByteCode, &width, &height) == -1)
exit (1);
if (!coordFlag)
printf ("image size: %dx%d, PCC length = %d\n", width, height, nByteCode);
imgSize.x = width;
imgSize.y = height;
/* allocate space for data coordinate array */
if ((data = (struct point *)
calloc (nByteCode * MAXPERCODE, sizeof (long))) == NULL) {
printf ("FITPOLYG: not enough memory -- sorry");
return (-1);
}
/* construct tables of feature chain decodes */
pccdecodes ();
/* perform feature chain decoding */
pcc2xy (data, &nData);
data[nData++].x = -STOPCODE;
if ((data = (struct point *)
realloc (data, nData * sizeof (struct point))) == NULL) {
printf ("FITPOLYG: not enough memory -- sorry");
return (-2);
}
/* find x,y coordinates for each line */
if (xytoline (data, &nData, &nSegments, &nStructs) < 0)
return (-1);
/* allocate output image */
imgO = ImageAlloc (height, width, 8);
image = ImageGetPtr (imgO);
/* initialize image */
for (y = 0; y < height; y++)
for (x = 0; x < width; x++)
image[y][x] = 255;
/* determine polygonal fits */
kLine = 0;
for (i = 0, nFits = 0; i < nData; i++) {
if (data[i].x != -1) {
pt0.x = data[i].x;
pt0.y = data[i].y;
i++;
if (data[i].x < 0) { /* one pixel line */
image[pt0.y][pt0.x] = 255;
if (coordFlag != 0)
printf ("%d: (%d,%d) (%d,%d) %d\n", nFits, pt0.x, pt0.y, pt0.x, pt0.y, kLine);
if (segfileFlag)
fprintf (segstream, "%4d %3d %3d %3d %3d %7.2f %3d\n",
nFits, pt0.x, pt0.y, pt0.x, pt0.y,
slope (pt0.x, pt0.y, pt0.x, pt0.y), kLine);
nFits++;
kLine++;
}
lengthSqr = area = 0;
while (data[i].x >= 0) {
x = data[i].x - pt0.x;
y = data[i].y - pt0.y;
deltaX = data[i].x - data[i - 1].x;
deltaY = data[i].y - data[i - 1].y;
lengthSqr += 2 * (x * deltaX + y * deltaY)
+ deltaX * deltaX + deltaY * deltaY;
area += x * deltaY - y * deltaX;
if ((area * area) > (thresh * lengthSqr)) {
pt1.x = data[i].x;
pt1.y = data[i].y;
drawline8 (image, imgSize, pt0, pt1, 0);
if (coordFlag != 0)
printf ("%d: (%d,%d) (%d,%d) %d\n", nFits, pt0.x, pt0.y, pt1.x, pt1.y, kLine);
if (segfileFlag)
fprintf (segstream, "%4d %3d %3d %3d %3d %7.2f %3d\n",
nFits, pt0.x, pt0.y, pt1.x, pt1.y,
slope (pt0.x, pt0.y, pt1.x, pt1.y), kLine);
nFits++;
pt0.x = data[i].x;
pt0.y = data[i].y;
lengthSqr = area = 0;
}
i++;
}
if (lengthSqr > 0) {
pt1.x = data[i - 1].x;
pt1.y = data[i - 1].y;
drawline8 (image, imgSize, pt0, pt1, 0);
if (coordFlag != 0)
printf ("%d: (%d,%d) (%d,%d) %d\n", nFits, pt0.x, pt0.y, pt1.x, pt1.y, kLine);
if (segfileFlag)
fprintf (segstream, "%4d %3d %3d %3d %3d %7.2f %3d\n",
nFits, pt0.x, pt0.y, pt1.x, pt1.y,
slope (pt0.x, pt0.y, pt1.x, pt1.y), kLine);
nFits++;
}
kLine++;
--i;
}
}
if (!coordFlag)
printf ("Number of segments fit to data = %d.\n", nFits);
if (segfileFlag) {
fseek (segstream, 0L, SEEK_SET);
fprintf (segstream, "%d %d %d", nFits, width, height);
fclose (segstream);
}
/* write image output file */
ImageOut (argv[2], imgO);
return (0);
}
/* USAGE: function gives instructions on usage of program
* usage: usage (flag)
* When flag is 1, the long message is given, 0 gives short.
*/
long
usage (flag)
short flag; /* flag =1 for long message; =0 for short message */
{
/* print short usage message or long */
printf ("USAGE: fitpolyg infile outimg [-t THRESHOLD] [-c] [-w file] [-L]\n");
if (flag == 0)
return (-1);
printf ("\nfitpolyg performs polygonal line fitting to image\n");
printf ("lines; straight line fits are made to portions of each segment\n");
printf ("to best approximate the chain of points comprising the segment;\n");
printf ("a segment is a chain of points between features, either\n");
printf ("endpoint features or junction features.\n\n");
printf ("ARGUMENTS:\n");
printf (" infile: input filename (PCC)\n");
printf (" outimg: output image filename (TIF)\n\n");
printf ("OPTIONS:\n");
printf (" -t THRESH: threshold on error for polygonal fit (default = %d);\n", THRESH_DFLT);
printf (" the smaller is this threshold, the closer will be the\n");
printf (" polygonal fit to the original data, but the more straight\n");
printf (" line fit segments will be required.\n");
printf (" -c: when set, prints out the (x,y) coordinates of the\n");
printf (" polygonal fit endlines.\n");
printf (" -w file: save line segment data to a file(.seg) for analysis by xsgll\n");
printf (" -L: print Software License for this module\n");
return (-1);
}
/* INPUT: function reads input parameters
* usage: input (argc, argv, &thresh, &coordFlag)
*/
#define USAGE_EXIT(VALUE) {usage (VALUE); return (-1);}
long
input (argc, argv, thresh, coordFlag, segfile)
int argc;
char *argv[];
long *thresh; /* threshold on polygonal fit */
short *coordFlag; /* flag = 1, print coordinates of fit; or 0 */
char *segfile; /* filename for saving segment data */
{
long n;
if (argc == 1)
USAGE_EXIT (1);
if (argc == 2)
USAGE_EXIT (0);
*thresh = THRESH_DFLT;
*coordFlag = 0;
for (n = 3; n < argc; n++) {
if (strcmp (argv[n], "-t") == 0) {
if (++n == argc)
usage (0);
*thresh = (long) atol (argv[n]);
}
if (strcmp (argv[n], "-w") == 0) {
if (++n == argc)
usage (0);
strcpy (segfile, argv[n]);
}
else if (strcmp (argv[n], "-c") == 0)
*coordFlag = 1;
else if (strcmp (argv[n], "-L") == 0) {
print_sos_lic ();
exit (0);
}
else
USAGE_EXIT (0);
}
return (0);
}
float
slope (int x1, int y1, int x2, int y2)
{
float m;
if ((x2 - x1) == 0) {
if (y2 - y1 == 0)
m = (float) 0.0;
else
m = (float) 512.0; /* slope = 512/1 */
}
else
m = ((float) (y2 - y1)) / ((float) (x2 - x1));
return (m);
}